package model.market;

import java.util.ArrayList;
import java.util.List;

import model.trader.Trader;


public class Trade {
	
	public final static boolean BUY = true;
	public final static boolean SELL = false;
	
	private int quantity;
	private int assetReference=-1;//AM: little check that it gets set.
	private boolean direction;
	private Trader initiator;
	private double limitPrice=0;
	private int executedPeriod;
	
	public int getAssetReference() {
		return assetReference;
	}

	public int getExecutedPeriod(){
		return executedPeriod;
	}
	private List<Execution> executions=new ArrayList<Execution>();
	
	public void addExecution(Execution exec){
		this.executedPeriod = exec.getPeriod();
		executions.add(exec);
	}
	
	public Trader getInitiator() {
		return initiator;
	}

	public boolean isMarketOrder(){
		return limitPrice==0;
	}
	
	/**
	 * This instruction will execute regardless of market price.
	 * @param intiator
	 * @param quantity
	 * @param direction
	 */
	public Trade(Trader intiator,int assetReference,int quantity){
		this(intiator,assetReference,quantity,0);
		
	}


	/**
	 * fully Customisable constructor, used to set up sitting passive offers by opportunists 
	 * @param initiator
	 * @param strategy
	 * @param quantity
	 * @param price
	 */
	public Trade(Trader initiator,
			int assetReference,
			int quantity, 
			double limitPrice) {
		this.initiator=initiator;
		this.assetReference=assetReference;
		setQuantity(quantity);
		direction=quantity>0;
		setLimitPrice(limitPrice);
	}

	public boolean getDirection() {
		return direction;
	}
	

	public double getLimitPrice() {
		return limitPrice;
	}

	public void setLimitPrice(double priceMovementLimit) {
		this.limitPrice = priceMovementLimit;
	}

	
	public int getQuantity() {
		return quantity;
	}
	
	private void setQuantity(int quantity){
		this.quantity = Math.abs(quantity);
	}

	
	public boolean isComplete(){
		int quantity = 0;
		for (int i=0;i<executions.size();i++){
			Execution exec = executions.get(i);
			quantity+=exec.getQuantity();
		}
		return getExecutedQuantity()==getQuantity();
	}
	
	public int getExecutedQuantity(){
		int quantity = 0;
		for (int i=0;i<executions.size();i++){
			Execution exec = executions.get(i);
			quantity+=exec.getQuantity();
		}
		return quantity;
	}
	
	public double getExecutedPrice(){
		
		double totalPaid = 0;
		for (int i=0;i<executions.size();i++){
			Execution exec = executions.get(i);
			totalPaid+=exec.getPrice()*exec.getQuantity();
		}
		double executedQuantity = getExecutedQuantity();
		double price=0;
		if(executedQuantity>0){
			price = totalPaid/executedQuantity;
		}
		if(Double.isNaN(price)){
			throw new RuntimeException("Executed price is  NAN? "+getExecutedQuantity());
		}
		return price;
	}
	
	
	
	
	@Override
	public String toString() {
		return "Trade[Asset "+assetReference+" Quantity: "+ quantity+" Direction: "+direction+" Trader: "+initiator+ " Limit: "+limitPrice+"]";
	}

	//Not intended for use... just helps with testing..
	public void clearExecutions() {
		executions.clear();
	}
}
